/*
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#include "MapEditor.hpp"
#include <Carbon/Carbon.h>
#include <SDL/SDL_syswm.h> 
#if !(defined(__APPLE__))
#include <gtk/gtk.h>
GtkWidget *OurWindow;
#else
#endif

#include <vector>

// Used Internally
void* AddImage(int ID, void* Two);
void * SelectTool(int ID, void *Two);

enum ToolType
{
	TOOL_MOVE = 0,
	TOOL_SELECT,
	TOOL_PATH,
	TOOL_PATH_ERASE,
};
class sToolOptions
{
	public:
		int LastX, LastY, InX, InY;
		int Radius;
		// Must use long long or GCC Bitches in 64bit from losing precision.
		long long Tool;
		sToolOptions()
		{
			Tool = TOOL_MOVE;
			LastX = -1;
			LastY = -1;
			InX = -1;
			InY = -1;
			Radius = -1;
		}
};

int SelectedObject = -1;
sToolOptions Tool;
tex CheckBox;

class sMenuOptions
{
	public:
		bool Open;
		int X;
		int Y;
		int SelectedItem;
		int SelectedSubItem;
		sMenuOptions()
		{
			SelectedItem = -1;
			SelectedSubItem = -1;
		}
		class cItems
		{
			public:
				std::string Name;
				void* (*Callback)(int, void*);
				void * Parameter;
				tex *IMG;
				cItems( std::string _Name, void* (*_Callback)(int ID, void*), void* _Parameter)
				{
					Name = _Name;
					Callback = _Callback;
					Parameter = _Parameter;
					IMG = NULL;
				}
				~cItems()
				{
				}
				void Call(int _ID)
				{
					Callback( _ID, Parameter);
				}
				std::vector<cItems> SubItems; // Not Yet working, do not add anything here yet
		};
		void DrawMenu()
		{
			DrawRect(X, Y, X + 64, Y + MenuItems.size() * 8, 0, 0, 0, 128);
			for(unsigned int a = 0;a < MenuItems.size(); ++a)
			{
				if(SelectedItem == a)
				{
					// Draws another box on top of the menu to make a black selection
					DrawRect(X, Y + a * 8, X + 64, Y + (a + 1) * 8 , 0, 0, 0, 255); 
					if(HasChildren(a))
					{
						//If it has children, draw them since we are hovering over the current box
						for(unsigned int b = 0; b < MenuItems[a].SubItems.size(); ++b)
						{
							if(SelectedSubItem == b)
								// Means that we have this subitem selected
								DrawRect(X + 64, Y + a * 8 + b * 8, X + 128, Y + a * 8 + (b + 1) * 8, 0, 0, 0, 255);
							// Draw a rectangle right next to the main menu box
							DrawRect(X + 64, Y + a * 8 + b * 8, X + 128, Y + a * 8 + (b + 1) * 8, 0, 0, 0, 128);
							DrawString(X + 64, Y + a * 8 + b * 8, MenuItems[a].SubItems[b].Name, 8, 8, 255, 255, 255, 128);
							if(MenuItems[a].SubItems[b].IMG)
								DrawPic(X + 64 + 56,Y + a * 8 + b * 8, 8, 8, *MenuItems[a].SubItems[b].IMG);
						}
					}
				}
				DrawString(X, Y + a * 8, MenuItems[a].Name, 8, 8, 255, 255, 255, 128);
				if(MenuItems[a].IMG)
					DrawPic(X + 56,Y + a * 8, 8, 8, *MenuItems[a].IMG);
				// If the Menu Item actually DOES have children, let us draw a notifier just so we know
				if(HasChildren(a))
					DrawRect(X + 60, Y + a * 8, X + 64, Y + (a + 1) * 8, 255, 0 , 0, 255);
			}
		}
		// Does this create a memory leak when we have sub children?
		// TODO: Find out if it does
		void DestroyMenu()
		{
			X = -1;
			Y = -1;
			MenuItems.clear();
		}
		// Adds a Menu Item and returns the ID of it
		// If the Callback is null, when you click on it, the menu won't do anything.
		int AddMenuItem(const char *_Name, void* (*_Callback)(int ID, void*), void *_Parameter)
		{
			MenuItems.push_back(cItems(_Name, _Callback, _Parameter));
			return MenuItems.size() - 1;
		}
		// Adds a submenu item to the parent and returns the ID of it
		// REMEMBER! It returns the ID of the CHILD item inside the parent
		// If the Callback is null, when you click on it, the menu won't do anything.
		int AddSubMenuItem(int _Parent, const char *_Name, void* (*_Callback)(int ID, void*), void *_Parameter)
		{
			MenuItems[_Parent].SubItems.push_back(cItems(_Name, _Callback, _Parameter));
			return MenuItems[_Parent].SubItems.size() - 1;
		}
		void AttachMenuIMG(int _Parent, int _Child, tex *_IMG)
		{
			if(_Child == -1) // Just adding to a parent
			{
				MenuItems[_Parent].IMG = _IMG;
			}
			else
			{
				//If the Parent is invalid, it won't work
				if(_Parent == -1)
					return;
				// If it doesn't have children and we are trying to add to a child, that makes no sense
				if(!HasChildren(_Parent))
					return;
				MenuItems[_Parent].SubItems[_Child].IMG = _IMG;
			}
		}
		// Checks if the item has children
		// REMEMBER! This only works if it's a toplevel menu item, sub sub items won't work
		bool HasChildren(int Item)
		{
			// Return false if the Inquired item is less than 0 since std::vector's can't hold negative values
			if(Item < 0)
				return false;
				
			if(MenuItems[Item].SubItems.size() == 0)
				return false;
			else
				return true;
		}
		void CreateMenu()
		{
			//TODO: Add images to the menus
			// Will be useful for checkboxes in the right click menu
			// Also helpful for knowing which tool is currently selected
			AddMenuItem("Add IMG", AddImage, NULL);
			int ToolID = AddMenuItem("Tools", NULL, NULL);
				AddSubMenuItem(ToolID, "Move", SelectTool, (void*)0); 
				AddSubMenuItem(ToolID, "Select", SelectTool, (void*)1);
				AddSubMenuItem(ToolID, "PPen", SelectTool, (void*)2);
				AddSubMenuItem(ToolID, "PErase", SelectTool, (void*)3);
				for(int a = 0; a < 4; ++a)
				{
					if(a == Tool.Tool)
						AttachMenuIMG(ToolID, a, &CheckBox);
					else
						AttachMenuIMG(ToolID, a, NULL);
				}
				// Casting from int to void* is a bit nasty, but it needs to be done so we can get multiple different data types across
			MousePosition(&X, &Y);
		}
		std::vector<cItems> MenuItems;
};
enum PropTypes
{
	TYPE_TEXT = 0,
	TYPE_IMAGE,
	TYPE_DRAW,
	TYPE_HBOX,
};
class sMapProperties
{
	public:
		// These are the starting positions of the properties
		// Probably not needed, but it may be useful in the future;
		int X;
		int Y;
		// These are the text sizes
		int TX;
		int TY;
		sMapProperties()
		{
			X = 800;
			Y = 0;
			TX = 8;
			TY = 8;
		}
		// This class is nearly a copy of the one in the right click menu
		class cItems
		{
			public:
				PropTypes Type;
				std::string Name;
				void* (*Callback)(int, void*);
				void * Parameter;
				void (*DrawFunction)(int, int, int, int);
				// Should we allow small images like the right click menu?
				cItems( const char* _Name, PropTypes _Type, void* (*_Callback)(int ID, void*), void* _Parameter)
				{
					cItems(std::string(_Name), _Type, _Callback, _Parameter);
				}
				cItems( std::string _Name, PropTypes _Type, void* (*_Callback)(int ID, void*), void* _Parameter)
				{
					Name = _Name;
					Type = _Type;
					Callback = _Callback;
					Parameter = _Parameter;
				}
				cItems(void* (*_Callback)(int ID, void*), void* _Parameter, void (*_DrawFunction)(int, int, int, int))
				{
					Name = "";
					Type = TYPE_DRAW;
					Callback = _Callback;
					DrawFunction = _DrawFunction;
				}
				~cItems()
				{
				}
				void Call(int _ID)
				{
					Callback( _ID, Parameter);
				}
				int Insert(cItems &_iTem)
				{
					SubItems.push_back(_iTem);
					return SubItems.size() - 1;
				}
				int Insert(std::string _Name, void* (*_Callback)(int ID, void*), void* _Parameter)
				{
					SubItems.push_back(cItems(_Name, TYPE_TEXT, _Callback, _Parameter));
					return SubItems.size() - 1;
				}
				int Insert(void* (*_Callback)(int ID, void*), void* _Parameter, void (*_DrawFunction)(int, int, int, int))
				{
					SubItems.push_back(cItems(_Callback, _Parameter, _DrawFunction));
					return SubItems.size() - 1;
				}
			std::vector<cItems> SubItems; //Currently Only used with TYPE_HBOX
		};
		void Clear()
		{
			MenuItems.clear();
		}
		void Draw()
		{
			for(unsigned int a = 0;a < MenuItems.size(); ++a)
			{
				switch(MenuItems[a].Type)
				{
					case TYPE_TEXT: // Text
						DrawString(X, Y + a * TY, MenuItems[a].Name, TX, TY, 255, 255, 255, 128);
					break;
					case TYPE_IMAGE: // Image
						printf("We aren't Ready for Image drawing yet!\n");
						exit(-1);
					case TYPE_DRAW: // Custom Draw
						MenuItems[a].DrawFunction(X, Y + a * TY, 400, TY);
					break;
					case TYPE_HBOX:
						printf("Aren't ready for drawing hbox yet!\n");
						break;
					default: // Whatever
					break;
				}
			}
		}
		/*void HandleInput()
		{
			if(MouseLeft && SelectedObject !=-1 && Map.Objects[SelectedObject].Type == 0)
			{
				int Selected = (MY - Y) / TY;
				if(MenuItems[Selected].Callback)
					MenuItems[Selected].Callback(Selected, Parameter);
			}
		}*/
		int Insert(cItems &_iTem)
		{
			MenuItems.push_back(_iTem);
			return MenuItems.size() - 1;
		}
		int Insert(std::string _Name, void* (*_Callback)(int ID, void*), void* _Parameter)
		{
			MenuItems.push_back(cItems(_Name, TYPE_TEXT, _Callback, _Parameter));
			return MenuItems.size() - 1;
		}
		int Insert(void* (*_Callback)(int ID, void*), void* _Parameter, void (*_DrawFunction)(int, int, int, int))
		{
			MenuItems.push_back(cItems(_Callback, _Parameter, _DrawFunction));
			return MenuItems.size() - 1;
		}
		std::vector<cItems> MenuItems;
};
sMapProperties::cItems ImageBox("ImageBox", TYPE_HBOX, NULL, NULL);
// Our GTK Thread
SDL_Thread *GTKThread = NULL;

sMenuOptions MenuOptions;
sMapProperties MapSettings; 
cMap Map;

void * SelectTool(int ID, void *Two)
{
	// The Second argument is actually the tool number we want
	// Cast from void* to long long, is pretty horrible looking, but you get the hang of it
	// long long is a 64bit value in 64bit Linux, Is it 32bit in 32bit? Not sure, but it's needed instead of int
	// since precision loss makes GCC cry in it's sleep.
	// Anyway, this sets the tool we are actually using finally
	Tool.Tool = (long long)Two;
	switch(Tool.Tool) // Just if we want to do something special when we switch tools
	{
		case TOOL_PATH: // Allows us to change to default radius if one wasn't selected yet
		case TOOL_PATH_ERASE:
			if(Tool.Radius == -1) // Also keeps last selected radius if there was one
				Tool.Radius = 25;
		break;
		default:
		break;
	}
	return 0;
}
void * SelectIMG(int _ID, void *Two)
{
	long long ID = (long long)Two;
	// ID represents the IMG number we select
	SelectedObject = ID;
	return 0;
}
#if defined(__APPLE__)
char *ConvertCFString(CFStringRef String){
	if( String == NULL)
		return "";
	int nameLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(String), kCFStringEncodingASCII);
    char *name = (char*)malloc(nameLength + 1);
	if(nameLength == 0 || name == NULL)
		return "";
    assert(name != NULL);
	int success = CFStringGetCString(String, name, nameLength + 1, kCFStringEncodingASCII);
	return name;
}
void* AddImage(int ID, void* Two)
{

	
}
#else
void* AddImage(int ID, void* Two)
{
	gdk_threads_enter();
	GtkWidget *dialog;
	GtkFileFilter *Filter;
	Filter = gtk_file_filter_new();
	gtk_file_filter_add_pattern (Filter, "*.png");
	
	dialog = gtk_file_chooser_dialog_new ("Open PNG File",
				      GTK_WINDOW (OurWindow),
				      GTK_FILE_CHOOSER_ACTION_OPEN,
				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
				      NULL);
	gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), Filter);
	
	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
	{
		char *filename;
		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
		Map.Objects.push_back(cMap::cObject(filename, MenuOptions.X, MenuOptions.Y, 0));
		SelectedObject = Map.Objects.size() - 1;
		g_free (filename);
	}
	gtk_widget_destroy (dialog);
	gdk_threads_leave();
	return 0;
}
#endif
void *SwapLoadType(int ID, void *Two)
{
	int _SelectedObject = (long long)Two;
	// This is probably a memory leak, need to fix it
	if(Map.Objects[_SelectedObject].Image.LoadType == 0) // Currently Stencil
		Map.Objects[_SelectedObject].Image = LoadTextureA(Map.Objects[_SelectedObject].Image.Filename);
	else // Currently Alpha
		Map.Objects[_SelectedObject].Image = LoadTexture(Map.Objects[_SelectedObject].Image.Filename);
	return 0;
}
#if defined(__APPLE__)
void *SelectColorCallback(int ID, void *Two)
{
}
#else
void *SelectColorCallback(int ID, void *Two)
{
	gdk_threads_enter();
	GtkWidget* ColorSelection = gtk_color_selection_dialog_new("Choose Color");
	GdkColor Color;
	Color.red = (65535 / 255) * Map.Objects[SelectedObject].Image.R;
	Color.green = (65535 / 255) * Map.Objects[SelectedObject].Image.G;
	Color.blue = (65535 / 255) * Map.Objects[SelectedObject].Image.B;
	gtk_color_selection_set_current_color(GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (ColorSelection)->colorsel), &Color);
	if (gtk_dialog_run (GTK_DIALOG (ColorSelection)) == GTK_RESPONSE_OK)
	{
		gtk_color_selection_get_current_color(GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (ColorSelection)->colorsel), &Color);
		printf("Given Color is RGB(%d,%d,%d)\n", Map.Objects[SelectedObject].Image.R, Map.Objects[SelectedObject].Image.G, Map.Objects[SelectedObject].Image.B);
		printf("Selected Color is RGB(%d,%d,%d)\n", (255 * Color.red) / 65535 , (255 * Color.green) / 65535, (255 * Color.blue) / 65535);
		Map.Objects[SelectedObject].Image = LoadTexture(Map.Objects[SelectedObject].Image.Filename, (255 * Color.red) / 65535 , (255 * Color.green) / 65535, (255 * Color.blue) / 65535);
	}
	gtk_widget_destroy (ColorSelection);
	gdk_threads_leave();
	return 0;
}
#endif
void DrawColorRect(int X, int Y, int W, int H)
{
	DrawRect(X, Y, X + W,Y + H, Map.Objects[SelectedObject].Image.R, Map.Objects[SelectedObject].Image.G, Map.Objects[SelectedObject].Image.B, 255);
}
#if defined(__APPLE__)
void *ChangeXY(int ID, void *Two)
{
}
void *ChangeWH(int ID, void *Two)
{
}
#else
void *ChangeXY(int ID, void *Two)
{
	int _SelectedObject = (long long)Two;
	gdk_threads_enter();
	GtkWidget *dialog, *label;
	char Temp[128];
   
   /* Create the widgets */
	dialog = gtk_dialog_new_with_buttons ("Change X and Y",
										 NULL,
										 GTK_DIALOG_DESTROY_WITH_PARENT,
										 GTK_STOCK_OK,
										 GTK_RESPONSE_OK,
										 NULL);
	label = gtk_entry_new ();
	sprintf(Temp, "(%d,%d)", Map.Objects[_SelectedObject].X, Map.Objects[_SelectedObject].Y);
	gtk_entry_set_text(GTK_ENTRY (label), Temp);
	gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
	gtk_widget_show(label);
	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
	{
		const gchar* Temp2 = gtk_entry_get_text(GTK_ENTRY (label));
		sscanf(Temp2, "(%d,%d)", &Map.Objects[_SelectedObject].X, &Map.Objects[_SelectedObject].Y);
	}
	// TODO: Should we destroy the label as well?
	gtk_widget_destroy(dialog);
	gdk_threads_leave();
	return 0;
}
void *ChangeWH(int ID, void *Two)
{
	int _SelectedObject = (long long)Two;
	gdk_threads_enter();
	GtkWidget *dialog, *label;
	char Temp[128];
   
   /* Create the widgets */
	dialog = gtk_dialog_new_with_buttons ("Change Width and Height",
										 NULL,
										 GTK_DIALOG_DESTROY_WITH_PARENT,
										 GTK_STOCK_OK,
										 GTK_RESPONSE_OK,
										 NULL);
	label = gtk_entry_new ();
	sprintf(Temp, "(%d,%d)", Map.Objects[_SelectedObject].W, Map.Objects[_SelectedObject].H);
	gtk_entry_set_text(GTK_ENTRY (label), Temp);
	gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
	gtk_widget_show(label);
	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
	{
		const gchar* Temp2 = gtk_entry_get_text(GTK_ENTRY (label));
		sscanf(Temp2, "(%d,%d)", &Map.Objects[_SelectedObject].W, &Map.Objects[_SelectedObject].H);
	}
	// TODO: Should we destroy the label as well?
	gtk_widget_destroy(dialog);
	gdk_threads_leave();
	return 0;
}
#endif
void *SwapMaintainRatio(int ID, void *Two)
{
	int _SelectedObject = (long long)Two;
	Map.Objects[_SelectedObject].Maintain = !Map.Objects[_SelectedObject].Maintain;
	return 0;
}
void *ShowPathSwitch(int ID, void *Two)
{
	Map.ShowPath = !Map.ShowPath;
	return 0;
}
// This thread isn't required since we aren't using gtk under Mac OSX
#if !(defined(__APPLE__))
int OurThread(void *DAta)
{
	gdk_threads_enter();
	gtk_main();
	gdk_threads_leave();
	return 0;
}
#endif
void DrawMap()
{
	// Started Showing Information on the right now, probably not needed anymore
	bool ShowAdditional = false;
	for(unsigned int a = 0;a < Map.Objects.size(); ++a)
	{
		DrawPic(Map.Objects[a].X, Map.Objects[a].Y, Map.Objects[a].W, Map.Objects[a].H, Map.Objects[a].Image);
		if(SelectedObject == a)
		{
			DrawBox(Map.Objects[a].X, Map.Objects[a].Y, Map.Objects[a].X + Map.Objects[a].W, Map.Objects[a].Y + Map.Objects[a].H, 255, 0, 0, 128); 
			if(ShowAdditional) // Shows X and Y and Width and Height of the selected image
			{
				char temp[32];
				sprintf(temp, "%d,%d", Map.Objects[a].X, Map.Objects[a].Y); // Put the X and Y coordinates of the texture in a string
				DrawRect(Map.Objects[a].X, Map.Objects[a].Y - (Map.Objects[a].Y - 8 < 0 ? - 8 : 8), Map.Objects[a].X + strlen(temp)*8, Map.Objects[a].Y, 0, 0, 0, 128); // Draw a box the X and Y coordinate text to be in
				DrawString(Map.Objects[a].X, Map.Objects[a].Y - (Map.Objects[a].Y - 8 < 0 ? 0 : 8), temp, 8, 8, 255, 255, 255, 128); // Draw the X and Y string in the box
				sprintf(temp, "%d,%d", Map.Objects[a].W, Map.Objects[a].H); // Put the Width and Height in the string.
				// This is a bit confusing so I'll explain it if asked
				DrawRect(Map.Objects[a].X + Map.Objects[a].W - strlen(temp) * 8, Map.Objects[a].Y + Map.Objects[a].H, Map.Objects[a].X + Map.Objects[a].W, Map.Objects[a].Y + Map.Objects[a].H + 8, 0, 0, 0, 128);
				DrawString(Map.Objects[a].X + Map.Objects[a].W - strlen(temp) * 8, Map.Objects[a].Y + Map.Objects[a].H, temp, 8, 8, 255, 255, 255, 128);
			}
		}
	}
	if(Map.ShowPath)
	{
		bool Currently = Map.Path[0];
		for(int Y = 0;Y < Map.Height; ++Y)
			for(int X = 0; X < Map.Width; ++X)
			{
				if(!Map.Path[Y * Map.Width + X])
					DrawPixel(X, Y, 255, 0, 0, 100);
				/*
				if(X == 0) // Start of the Line
				{
					if(Map.Path[Y * Map.Width + X])
						BeginLine(X, Y, 0, 255, 0, 100);
					else
						BeginLine(X, Y, 255, 0, 0, 100);
					Currently = Map.Path[Y * Map.Width + X];
				}
				if(X == (Map.Width - 1)) // End of the map
				{
					EndLine(X + 1, Y);
				}
				if(Currently != Map.Path[Y * Map.Width + X]) // Changing
				{
					EndLine(X, Y);
					if(Map.Path[Y * Map.Width + X])
						BeginLine(X, Y, 0, 255, 0, 100);
					else
						BeginLine(X, Y, 255, 0, 0, 100);
					Currently = Map.Path[Y * Map.Width + X];
				}*/
			}
	}
	// If Our tool is the Path tool, draw a square around the mouse pointer
	if(Tool.Tool == TOOL_PATH || Tool.Tool == TOOL_PATH_ERASE)
	{
		DrawBoxCenter(Tool.LastX, Tool.LastY, Tool.Radius, Tool.Radius, 0,0,0, 255);
	}
	// Covers up anything from map editor, so we don't get silliness
	DrawRect(800, 0, 1000, 600, 0,0,0,255);
	// Draw our settings on the right side
	// First check if our selected type is valid and if it's an image
	MapSettings.Draw();
}
void HandMapEditorInput()
{
	int MX = 0, MY = 0;
	bool MouseLeft = MousePressed(SDL_BUTTON_LEFT);
	MousePosition(&MX, &MY);
	if(MousePressed(SDL_BUTTON_RMASK) && MenuOptions.Open == false)
	{
		MenuOptions.Open = true;
		MenuOptions.CreateMenu();
	}
	
	if(MenuOptions.Open)
	{
		if(	MX >= MenuOptions.X && MX <= MenuOptions.X + 64 && 
			MY >= MenuOptions.Y && MY < (MenuOptions.Y + (MenuOptions.MenuItems.size()) * 8))
		{
			MenuOptions.SelectedItem = (MY - MenuOptions.Y) / 8;
			if(MouseLeft) // We clicked Left mouse button in the menu!
			{
				// We must check if the callback is valid, else we would crash. Also if it isn't valid, we will not close the menu since they didn't select anything
				if(MenuOptions.MenuItems[MenuOptions.SelectedItem].Callback)
				{
					MenuOptions.MenuItems[MenuOptions.SelectedItem].Call(MenuOptions.SelectedItem);
					MenuOptions.Open = false;
					MenuOptions.DestroyMenu();
				}
				return;
			}
		}
		else
		{
			if(MenuOptions.HasChildren(MenuOptions.SelectedItem))
			{
				// Seems we are not inside the main menu anymore
				// Let's see if we are in the Child menu now
				if(	MX >= MenuOptions.X + 64 && MX <= MenuOptions.X + 128 &&
					MY >= MenuOptions.Y + MenuOptions.SelectedItem * 8 && MY < MenuOptions.Y + MenuOptions.SelectedItem * 8 + MenuOptions.MenuItems[MenuOptions.SelectedItem].SubItems.size() * 8)
				{
					// Seems we are inside the submenu now, let us find which one we are currently hovering over
					MenuOptions.SelectedSubItem = (MY - MenuOptions.Y - MenuOptions.SelectedItem * 8) / 8;
					if(MouseLeft)
					{
						if(MenuOptions.MenuItems[MenuOptions.SelectedItem].SubItems[MenuOptions.SelectedSubItem].Callback)
						{
							MenuOptions.MenuItems[MenuOptions.SelectedItem].SubItems[MenuOptions.SelectedSubItem].Call(MenuOptions.SelectedSubItem);
							MenuOptions.Open = false;
							MenuOptions.DestroyMenu();
						}
					}
				}
			}
			else
			{
				MenuOptions.SelectedItem = -1;
				MenuOptions.SelectedSubItem = -1;
			}
		}
		if(MouseLeft)
		{
			if(	MX > (MenuOptions.X + 64) || MX < MenuOptions.X || 
				MY > (MenuOptions.Y + MenuOptions.MenuItems.size()*8) || MY < MenuOptions.Y ) // We clicked out of the menu while drawing, destroy and leave it
			{
				MenuOptions.Open = false;
				MenuOptions.DestroyMenu();
				return;
			}
		}
		return;
		// return now so that we don't run in to problems later on
	}
	if(!MenuOptions.Open)
	{
		
		switch(Tool.Tool)
		{
			case -1:
				// Should we even allow no tool to be selected?
				// Whatever, for now just break
			break;
			case TOOL_MOVE:
			{
				// Movement tool to move the images around
				// Can move via mouse or Keyboard
				// Mouse can't resize image yet, will be made available later
				if(MX >= 0 && MX < Map.Width && MY >=0 && MY < Map.Height) // Just a check to make sure we are in the map section
				{
					if(MouseLeft && SelectedObject != -1) // Checking where we clicked at if type is move
					{
						if(	MX >= Map.Objects[SelectedObject].X && MX <= (Map.Objects[SelectedObject].X + Map.Objects[SelectedObject].W) &&
							MY >= Map.Objects[SelectedObject].Y && MY <= (Map.Objects[SelectedObject].Y + Map.Objects[SelectedObject].H))
						{
							// If Inside this block, it means we have clicked inside of the image with the move tool
							if(Tool.LastX == -1 && Tool.LastY == -1) // Means this is the first time we've held it, Since Allows objects to the negative regions is going to be disallowed
							{
								Tool.LastX = MX;
								Tool.LastY = MY;
								Tool.InX = MX - Map.Objects[SelectedObject].X; // Tells us where we clicked inside the texture itself
								Tool.InY = MY - Map.Objects[SelectedObject].Y; // Same here, but on Y axis
							}
							else
							{
								int DX, DY; 
								// We must find the difference in the values
								DX = MX - Tool.LastX;
								DY = MY - Tool.LastY;
								Tool.LastX = MX;
								Tool.LastY = MY;
								Map.Objects[SelectedObject].X = Map.Objects[SelectedObject].X + DX;
								Map.Objects[SelectedObject].Y = Map.Objects[SelectedObject].Y + DY;
							}
						}
					}
				}
				if(!MouseLeft) // Not in MouseLeft and the Move tool is selected
				{
					// TODO: Make this a toolOption Function
					Tool.LastX = -1;
					Tool.LastY = -1;
					Tool.InX = -1;
					Tool.InY = -1;
				}
				if(SelectedObject != -1)
				{
					if(Map.Objects[SelectedObject].Type == 0) // 0 Being Image, should be a enum in the future TODO
					{
						if(ModPressed(KMOD_SHIFT))
						{
							if(KeyPressed(SDLK_LEFT))
							{
								// Theoretical time
								// W = 5
								// H = 10
								// Ratio = width/height
								// So the ratio is 5/10 or 1/2
								// so for every 1 pixel increase in W, we increase 2 in Height
								// to find that out, we switch the ratio to height/width
								// and get 10/5 or 2
								if(Map.Objects[SelectedObject].Maintain)
									Map.Objects[SelectedObject].H -= Map.Objects[SelectedObject].Image.Height/Map.Objects[SelectedObject].Image.Width;
								Map.Objects[SelectedObject].W--;
								
							}
							else if(KeyPressed(SDLK_RIGHT))
							{
								if(Map.Objects[SelectedObject].Maintain)
									Map.Objects[SelectedObject].H += Map.Objects[SelectedObject].Image.Height/Map.Objects[SelectedObject].Image.Width;
								Map.Objects[SelectedObject].W++;
							}
							else if(KeyPressed(SDLK_UP))
							{
								if(Map.Objects[SelectedObject].Maintain)
									Map.Objects[SelectedObject].W -= Map.Objects[SelectedObject].Image.Width/Map.Objects[SelectedObject].Image.Height;
								Map.Objects[SelectedObject].H--;
							}
							else if(KeyPressed(SDLK_DOWN))
							{
								if(Map.Objects[SelectedObject].Maintain)
									Map.Objects[SelectedObject].W += Map.Objects[SelectedObject].Image.Width/Map.Objects[SelectedObject].Image.Height;
								Map.Objects[SelectedObject].H++;
							}
						}
						else
						{
							if(KeyPressed(SDLK_LEFT))
								Map.Objects[SelectedObject].X--;
							if(KeyPressed(SDLK_RIGHT))
								Map.Objects[SelectedObject].X++;
							if(KeyPressed(SDLK_UP))
								Map.Objects[SelectedObject].Y--;
							if(KeyPressed(SDLK_DOWN))
								Map.Objects[SelectedObject].Y++;
						}
						// These are just a few checks to make sure we don't disappear off the edge of the map area
						// This will need to be changed later on for scrolling maps
						// TODO:
						if(Map.Objects[SelectedObject].X < 0)
							Map.Objects[SelectedObject].X = 0;
						if((Map.Objects[SelectedObject].X + Map.Objects[SelectedObject].W) > Map.Width)
							Map.Objects[SelectedObject].X = Map.Width - Map.Objects[SelectedObject].W;
						if(Map.Objects[SelectedObject].Y < 0)
							Map.Objects[SelectedObject].Y = 0;
						if((Map.Objects[SelectedObject].Y + Map.Objects[SelectedObject].H) > Map.Height)
							Map.Objects[SelectedObject].Y = Map.Height - Map.Objects[SelectedObject].W;	
					}
				}
			}
			break;
			case TOOL_SELECT:
			{
				// First make sure the menu isn't open, so we won't do anything when it actually is
				if(!MenuOptions.Open) 
				{
					// Check if we clicked somewhere with the left button
					if(MX >= 0 && MX < 800 && MY >=0 && MY < 600) // Just a check to make sure we are in the map section
					{
						if(MouseLeft)
						{
							// Seems we have
							// Let us loop through all the current textures on the screen and see if we have clicked on one
							// This has a chance of getting multiple images being able to be returned, but we are only handling the first one we encounter
							// TODO: 	Create a right click menu that will show all the overlapping textures and 
							// 			Allow us to select which one we want
							int _SelectedObject = -1;
							MenuOptions.AddMenuItem("Pick", NULL, NULL);
							MenuOptions.X = MX;
							MenuOptions.Y = MY;
							for(int a = 0; a < Map.Objects.size(); ++a)
							{
								if(	MX >= Map.Objects[a].X && MX <= Map.Objects[a].X + Map.Objects[a].W &&
									MY >= Map.Objects[a].Y && MY <= Map.Objects[a].Y + Map.Objects[a].H)
								{
									// Looks like we clicked an image
									// This if is highly likely of not working for reversed or upside down images
									_SelectedObject = a;
									char temp[16];
									sprintf(temp, "%d", a);
									int _ID = MenuOptions.AddMenuItem(temp, SelectIMG, (void*)a);
									MenuOptions.AttachMenuIMG(_ID, -1, &Map.Objects[a].Image);
									// If/When I create the right click menu, it won't break here
									// But we are just handling the first entry for now
								}
							}
							if(MenuOptions.MenuItems.size() > 2) // Means we have more than one selected
								MenuOptions.Open = true;
							else // Means there is only one, so just select it
							{
								SelectedObject = _SelectedObject;
								MenuOptions.DestroyMenu(); // Also destory the menu we created, so it doesn't mess with things
							}
							// This way we can deselect any objects as well
						}
					}
				}
			}
			break;
			case TOOL_PATH:
			case TOOL_PATH_ERASE:
				Tool.LastX = MX;
				Tool.LastY = MY;
				if(MouseLeft) // Draw our Path
				{
					for(int Y = Tool.LastY - Tool.Radius/2; Y < Tool.LastY + Tool.Radius/2; ++Y)
						for(int X = Tool.LastX - Tool.Radius/2; X < Tool.LastX + Tool.Radius/2; ++X)
						{
							if (!(X < 0 || X >= Map.Width || Y < 0 || Y > Map.Height))
								Map.Path[Y * Map.Width + X] = (Tool.Tool == TOOL_PATH) ? true : false;
						}
				}
			break;
		}
	}
	//Let's add the items for Map settings and handle their events
	MapSettings.Clear();
	if(SelectedObject != -1 && Map.Objects[SelectedObject].Type == 0)
	{
		MapSettings.Insert("Image Settings", NULL, NULL);
		MapSettings.Insert(Map.Objects[SelectedObject].Image.LoadType ? "Load Type: Alpha" : "Load Type: Stencil", SwapLoadType, (void*)SelectedObject);
		if(!Map.Objects[SelectedObject].Image.LoadType)
		{
			char Temp[8];
			sprintf(Temp, "R:%d\n", Map.Objects[SelectedObject].Image.R);
			MapSettings.Insert(Temp, NULL, NULL);
			sprintf(Temp, "G:%d\n", Map.Objects[SelectedObject].Image.G);
			MapSettings.Insert(Temp, NULL, NULL);
			sprintf(Temp, "B:%d\n", Map.Objects[SelectedObject].Image.B);
			MapSettings.Insert(Temp, NULL, NULL);
			MapSettings.Insert(SelectColorCallback, (void*)SelectedObject, DrawColorRect);
		}
		char Temp[32], Temp2[32];
		sprintf(Temp, "X,Y(%d,%d)", Map.Objects[SelectedObject].X, Map.Objects[SelectedObject].Y);
		MapSettings.Insert(Temp, ChangeXY, (void*)SelectedObject);
		sprintf(Temp, "W,H(%d,%d) ^R%d,%d", Map.Objects[SelectedObject].W, Map.Objects[SelectedObject].H, Map.Objects[SelectedObject].Image.Width, Map.Objects[SelectedObject].Image.Width);
		MapSettings.Insert(Temp, ChangeWH, (void*)SelectedObject);
		MapSettings.Insert(Map.Objects[SelectedObject].Maintain ? "Maintain Ratio? ^RYes" : "Maintain Ratio? ^RNo", SwapMaintainRatio, (void*)SelectedObject);
	}
	MapSettings.Insert("Map Settings", NULL, NULL);
	MapSettings.Insert(Map.ShowPath ? "Draw Path? ^RYes" : "Draw Path? ^RNo", ShowPathSwitch, NULL);
	if (MouseLeft && MX >= MapSettings.X)
	{
		int Selected = (MY - MapSettings.Y) / MapSettings.TY;
		if(Selected < MapSettings.MenuItems.size())
			if(MapSettings.MenuItems[Selected].Callback)
				MapSettings.MenuItems[Selected].Callback(Selected, MapSettings.MenuItems[Selected].Parameter);
	}
}
int MapEditor(int argc, char * const argv[])
{
	InitScreen(1000, 600);
	SDL_ShowCursor(true);
	InitMusic(argc,argv);
	GetInput();
	
	//Load our Checkbox img with alpha transparency
	CheckBox = LoadTextureA("Data/Check.png");
#if !(defined(__APPLE__))
    gdk_threads_init();
	gtk_init(&argc, (char***)&argv);
	// Must create a window or else GTK will freak out about not having a window
	OurWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	// Create a thread so we can run GTK_main in, so things actually update
	SDL_CreateThread( OurThread, NULL );
#endif
	// Running is set to false when we are shutting down
	while(Running)
	{
		CheckEvents();
		HandMapEditorInput();
		ClearScreen(); // Clear Screen so it's empty
		DrawRect(0, 0, 800, 600, 255, 255, 255, 255);
		DrawMap();
		if(MenuOptions.Open)
			MenuOptions.DrawMenu();
		DrawString(800, 600 - 16, FPS_Counter(), 16, 16, 255, 255, 0, 255);
		Swap(); // Swap screen so we see changes
	} 
#if !(defined(__APPLE__))
	gtk_main_quit ();
#endif
	return false;
}
